﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using CSA.Lib;

namespace CSA.Operator
{
    public class CrossOverOperator : ICSOperator
    {
        #region Fields
        CSPopulation m_OperatePopulation=null;
        String m_CurUsedFunctionName="";
        Hashtable m_FunctionNames = new Hashtable();       
        #endregion

        #region Properties   

        public String Name
        {
            get { return "CrossOverOperator"; }
        }

        public String Caption
        {
            get { return global::CSA.Operator.TextString.CrossOverCaption; }
        }

        public String Description
        {
            get { return global::CSA.Operator.TextString.CrossOverDes; }
        }

        public String Library
        {
            get { return "CSA.Operator"; }
        }

        public Hashtable Get_Parameters(String nFunctionName)
        {
            String nValidateName = "";
            if (nFunctionName.Trim() == "" || !m_FunctionNames.Contains(nFunctionName))
            {
                nValidateName = "DefaultCross";

            }
            else
            {
                nValidateName = nFunctionName;
            }
            CSFuntionInfo nDefulatParas = (CSFuntionInfo)m_FunctionNames[nValidateName];
            return nDefulatParas.Parameters;
        }

        public OperatorType OperatorType
        {
            get { return OperatorType.enumCustomOperator; }
        }

        public Hashtable FunctionNames
        {
            get { return m_FunctionNames; }
        }

        public bool UseCustomAntibodyOperator
        {
            get { return false; }
        }

        public CSFuntionInfo CustomAntibodyOperator
        {
            get { return null; }
            set { }
        }

        #endregion

        #region Methods

        public CrossOverOperator()
        {
            InitialParameters();
        }

        public bool Execute(CSPopulation nOperatePopulation, ref String nErrorStr, String nMethodName = "")
        {
            m_OperatePopulation = nOperatePopulation;
            if (nMethodName.Trim() == "" || !m_FunctionNames.Contains(nMethodName))
            {
                m_CurUsedFunctionName = "DefaultCross";
            }
            else
            {
                m_CurUsedFunctionName = nMethodName;
            }
            CSFuntionInfo nDefulatParas = (CSFuntionInfo)m_FunctionNames[m_CurUsedFunctionName];
            if (m_CurUsedFunctionName == "DefaultCross")
            {
                CSParameter CrossRate = (CSParameter)nDefulatParas.Parameters["CrossProbability"];
                Double nMuturationCoe = Convert.ToDouble(CrossRate.Value.ToString());
                CSPopulation nPop = nOperatePopulation;
                ICSOptimizationProblem nProblem = nOperatePopulation.ProblemInfo;
                List<CSAntibody> nNewPop = nPop.NewAntibodies;
                int nSize = nNewPop.Count;
                int nCrossCount = (int)(nSize * nMuturationCoe);
                CSAgorithmsHelper nHelper = new CSAgorithmsHelper();
                int nCount = 0;
                while (nCount < nCrossCount)
                {
                    int nID1 = nHelper.NextRandomNumber(0, nSize - 1);
                    int nID2 = nHelper.NextRandomNumber(0, nSize - 1);
                    if (nID1 != nID2)
                    {
                        CSAntibody nAb1 = nNewPop[nID1];
                        CSAntibody nAb2 = nNewPop[nID2];
                        if (nAb1 != null && nAb2 != null)
                        {
                            Int32 nLength = (Int32)nAb1.AntibodyLength;
                            Int32 nPos = nHelper.NextRandomNumber(1, nLength - 1);
                            List<bool> nCrossPos = new List<bool>();
                            for (int i = 0; i < nLength; i++)
                            {
                                nCrossPos.Add(false);
                            }
                            nCrossPos[nPos] = true;                          
                            nProblem.CrossoverAb(ref nAb1, ref nAb2, nCrossPos);                        
                            nCount++;
                        }
                    }
                }
                nNewPop.Sort(new AntibodyCompare());
            }
            return true;
        }

        public void InitialParameters()
        {

            m_FunctionNames.Clear();
            //Add Parameters
            CSFuntionInfo m_DefaultFunctionInfo = new CSFuntionInfo();
            m_DefaultFunctionInfo.Caption = global::CSA.Operator.TextString.DefaultFunction;
            m_DefaultFunctionInfo.Description = global::CSA.Operator.TextString.DefaultCrossFunctionDes;
            m_DefaultFunctionInfo.Name = "DefaultCross";
            Hashtable nStandardFunctionPara = new Hashtable();
            float nDefaultClonalRate = 0.1F;  //
            CSParameter CrossRate = new CSParameter();
            CrossRate.Type = ParameterType.enumFloat;
            String nParaName1 = "CrossProbability";
            CrossRate.Caption = global::CSA.Operator.TextString.CrossRateCaption;
            CrossRate.Description =global::CSA.Operator.TextString.CrossRateDes;
            CrossRate.Name = nParaName1;
            CrossRate.Value = nDefaultClonalRate;
            CrossRate.DomainType = enumParasDomain.enumDomainExtent;
            String low1 = "0.001";
            String up1 = "0.8";
            List<String> nDomain = new List<string>();
            nDomain.Add(low1);
            nDomain.Add(up1);
            CrossRate.DomainValues = nDomain;
            nStandardFunctionPara.Add(nParaName1, CrossRate);
            m_DefaultFunctionInfo.Parameters = nStandardFunctionPara;
            m_FunctionNames.Add(m_DefaultFunctionInfo.Name, m_DefaultFunctionInfo);
        }

        #endregion
    }
}
